import { json, query, action, useParams, createAsync, useSubmission } from "@solidjs/router" import { createEffect, For, Show } from "solid-js" import { Provider } from "@opencode-ai/console-core/provider.js" import { withActor } from "~/context/auth.withActor" import { createStore } from "solid-js/store" import styles from "./provider-section.module.css" import { useI18n } from "~/context/i18n" import { formError, localizeError } from "~/lib/form-error" const PROVIDERS = [ { name: "OpenAI", key: "openai", prefix: "sk-" }, { name: "Anthropic", key: "anthropic", prefix: "sk-ant-" }, { name: "Google Gemini", key: "google", prefix: "AI" }, ] as const type Provider = (typeof PROVIDERS)[number] function maskCredentials(credentials: string) { return `${credentials.slice(0, 8)}...${credentials.slice(-8)}` } const removeProvider = action(async (form: FormData) => { "use server" const provider = form.get("provider") as string | null if (!provider) return { error: formError.providerRequired } const workspaceID = form.get("workspaceID") as string | null if (!workspaceID) return { error: formError.workspaceRequired } return json(await withActor(() => Provider.remove({ provider }), workspaceID), { revalidate: listProviders.key, }) }, "provider.remove") const saveProvider = action(async (form: FormData) => { "use server" const provider = form.get("provider") as string | null const credentials = form.get("credentials") as string | null if (!provider) return { error: formError.providerRequired } if (!credentials) return { error: formError.apiKeyRequired } const workspaceID = form.get("workspaceID") as string | null if (!workspaceID) return { error: formError.workspaceRequired } return json( await withActor( () => Provider.create({ provider, credentials }) .then(() => ({ error: undefined })) .catch((e) => ({ error: e.message as string })), workspaceID, ), { revalidate: listProviders.key }, ) }, "provider.save") const listProviders = query(async (workspaceID: string) => { "use server" return withActor(() => Provider.list(), workspaceID) }, "provider.list") function ProviderRow(props: { provider: Provider }) { const params = useParams() const i18n = useI18n() const providers = createAsync(() => listProviders(params.id!)) const saveSubmission = useSubmission( saveProvider, ([fd]) => (fd.get("provider") as string | null) === props.provider.key, ) const removeSubmission = useSubmission( removeProvider, ([fd]) => (fd.get("provider") as string | null) === props.provider.key, ) const [store, setStore] = createStore({ editing: false }) let input: HTMLInputElement const providerData = () => providers()?.find((p) => p.provider === props.provider.key) createEffect(() => { if (!saveSubmission.pending && saveSubmission.result && !saveSubmission.result.error) { hide() } }) function show() { while (true) { saveSubmission.clear() if (!saveSubmission.result) break } setStore("editing", true) setTimeout(() => input?.focus(), 0) } function hide() { setStore("editing", false) } return (
{i18n.t("workspace.providers.subtitle")}
| {i18n.t("workspace.providers.table.provider")} | {i18n.t("workspace.providers.table.apiKey")} |
|---|